package engine.logic.walk.Astar
{ 
	import flash.geom.Point;
	
	public class Grid 
	{ 
		private var _startNode:Node; 
		private var _endNode:Node; 
		private var _nodes:Array;
		private var _numCols:int;
		private var _numRows:int;
		
		public function Grid(numCols:int, numRows:int) 
		{ 
			_numCols=numCols; 
			_numRows=numRows; 
			_nodes=new Array();
			for (var i:int=0; i < _numCols; i++) 
			{ 
				_nodes[i] = new Array();
				for (var j:int=0; j < _numRows; j++) 
				{ 
					_nodes[i][j]=new Node(i, j); 
				} 
			} 
		} 
		
		public function getNode(x:int, y:int):Node 
		{ 
			return _nodes[x][y] as Node; 
		} 
		
		
		public function setEndNode(x:int, y:int):void
		{ 
			if(!_nodes[x][y]) return;
			_endNode=_nodes[x][y] as Node; 
		} 
		
		
		public function setStartNode(x:int, y:int):void
		{
			if(!_nodes[x][y]) return;
			_startNode=_nodes[x][y] as Node; 
		} 
		
		
		public function setWalkable(x:int, y:int, value:Boolean):void
		{
			if(!_nodes[x][y]) return;
			_nodes[x][y].walkable=value; 
		} 
		
		
		public function get endNode():Node 
		{ 
			return _endNode; 
		} 
		
		
		public function get numCols():int
		{ 
			return _numCols; 
		} 
		
		
		public function get numRows():int
		{ 
			return _numRows; 
		} 
		
		
		public function get startNode():Node 
		{ 
			return _startNode; 
		}
		
		/**
		 * 得到一个点下的所有节点 
		 * @param xPos		点的横向位置
		 * @param yPos		点的纵向位置
		 * @param exception	例外格，若其值不为空，则在得到一个点下的所有节点后会排除这些例外格
		 * @return 			共享此点的所有节点
		 * 
		 */		
		public function getNodesUnderPoint( xPos:Number, yPos:Number, exception:Array=null ):Array
		{
			var result:Array = [];
			var xIsInt:Boolean = xPos % 1 == 0;
			var yIsInt:Boolean = yPos % 1 == 0;
			
			if( xIsInt && yIsInt )
			{
				result[0] = getNode( xPos - 1, yPos - 1);
				result[1] = getNode( xPos, yPos - 1);
				result[2] = getNode( xPos - 1, yPos);
				result[3] = getNode( xPos, yPos);
			}
			else if( xIsInt && !yIsInt )
			{
				result[0] = getNode( xPos - 1, int(yPos) );
				result[1] = getNode( xPos, int(yPos) );
			}
			else if( !xIsInt && yIsInt )
			{
				result[0] = getNode( int(xPos), yPos - 1 );
				result[1] = getNode( int(xPos), yPos );
			}
			else
			{
				result[0] = getNode( int(xPos), int(yPos) );
			}
			
			if( exception && exception.length > 0 )
			{
				for( var i:int=0; i<result.length; i++ )
				{
					if( exception.indexOf(result[i]) != -1 )
					{
						result.splice(i, 1);
						i--;
					}
				}
			}
			
			return result;
		}
		
		public function hasBarrier( startX:int, startY:int, endX:int, endY:int ):Boolean
		{
			if( startX == endX && startY == endY )return false;
			
			var point1:Point = new Point( startX + 0.5, startY + 0.5 );
			var point2:Point = new Point( endX + 0.5, endY + 0.5 );
			
			var distX:Number = Math.abs(endX - startX);
			var distY:Number = Math.abs(endY - startY);									
			
			var loopDirection:Boolean = distX > distY ? true : false;
			
			var lineFuction:Function;
			
			var i:Number;
			
			var loopStart:Number;
			
			var loopEnd:Number;
			
			var passedNodeList:Array;
			var passedNode:Node;
			
			if( loopDirection )
			{				
				lineFuction = MathUtil.getLineFunc(point1, point2, 0);
				
				loopStart = Math.min( startX, endX );
				loopEnd = Math.max( startX, endX );
				
				for( i=loopStart; i<=loopEnd; i++ )
				{
					if( i==loopStart )i += .5;

					var yPos:Number = lineFuction(i);
					
					

					passedNodeList = getNodesUnderPoint( i, yPos );
					for each( passedNode in passedNodeList )
					{
						if( passedNode.walkable == false )return true;
					}
					
					if( i == loopStart + .5 )i -= .5;
				}
			}
			else
			{
				lineFuction = MathUtil.getLineFunc(point1, point2, 1);
				
				loopStart = Math.min( startY, endY );
				loopEnd = Math.max( startY, endY );
				

				for( i=loopStart; i<=loopEnd; i++ )
				{
					if( i==loopStart )i += .5;

					var xPos:Number = lineFuction(i);
					
					passedNodeList = getNodesUnderPoint( xPos, i );
					
					for each( passedNode in passedNodeList )
					{
						if( passedNode.walkable == false )return true;
					}
					
					if( i == loopStart + .5 )i -= .5;
				}
			}
			
			return false;			
		}
		
	} 
} 